<?php
/**
 * GouGuOA 文件预览API控制器
 * 实现现代化RESTful API标准，支持多种文件格式预览
 */

declare (strict_types=1);

namespace app\controller\home;

use app\BaseController;
use think\facade\Db;
use think\facade\Request;
use think\response\File;
use app\common\FileUploadConfig; // 导入全局文件上传配置类

// 引入辅助函数
require_once __DIR__ . '/functions.php';

class Preview extends BaseController
{
    /**
     * 获取文件预览信息
     * @param int $id 文件ID
     * @return \think\Response
     */
    public function read($id)
    {
        $file = Db::name('file')->where(['id' => $id, 'user_id' => $this->uid])->find();
        if (!$file) {
            return to_assign(1, '文件不存在或无权限访问');
        }

        // 根据文件类型确定预览方式
        $previewInfo = $this->getPreviewInfo($file);
        
        return to_assign(0, '获取成功', $previewInfo);
    }

    /**
     * 获取文件预览信息
     * @param array $file 文件信息
     * @return array 预览信息
     */
    private function getPreviewInfo($file)
    {
        $previewInfo = [
            'id' => $file['id'],
            'name' => $file['name'],
            'filepath' => $file['filepath'],
            'fileext' => $file['fileext'],
            'filesize' => $file['filesize'],
            'mimetype' => $file['mimetype'],
            'preview_type' => '', // 预览类型: image, pdf, office, video, audio, text, none
            'preview_url' => '', // 预览地址
            'download_url' => $file['filepath'], // 下载地址
        ];

        // 图片文件
        $imageExts = ['jpg', 'jpeg', 'png', 'gif', 'bmp', 'webp'];
        if (in_array(strtolower($file['fileext']), $imageExts)) {
            $previewInfo['preview_type'] = 'image';
            $previewInfo['preview_url'] = $file['filepath'];
            return $previewInfo;
        }

        // PDF文件
        if (strtolower($file['fileext']) === 'pdf') {
            $previewInfo['preview_type'] = 'pdf';
            $previewInfo['preview_url'] = $file['filepath'];
            return $previewInfo;
        }

        // Office文档
        $officeExts = ['doc', 'docx', 'xls', 'xlsx', 'ppt', 'pptx'];
        if (in_array(strtolower($file['fileext']), $officeExts)) {
            $previewInfo['preview_type'] = 'office';
            // 使用在线预览服务或转换为PDF后预览
            $previewInfo['preview_url'] = $this->convertToPreviewUrl($file);
            return $previewInfo;
        }

        // 视频文件
        $videoExts = ['mp4', 'avi', 'mov', 'wmv', 'flv', 'mkv'];
        if (in_array(strtolower($file['fileext']), $videoExts)) {
            $previewInfo['preview_type'] = 'video';
            $previewInfo['preview_url'] = $file['filepath'];
            return $previewInfo;
        }

        // 音频文件
        $audioExts = ['mp3', 'wav', 'wma', 'flac', 'midi'];
        if (in_array(strtolower($file['fileext']), $audioExts)) {
            $previewInfo['preview_type'] = 'audio';
            $previewInfo['preview_url'] = $file['filepath'];
            return $previewInfo;
        }

        // 文本文件
        $textExts = ['txt', 'log', 'md', 'csv'];
        if (in_array(strtolower($file['fileext']), $textExts)) {
            $previewInfo['preview_type'] = 'text';
            $previewInfo['preview_url'] = $file['filepath'];
            return $previewInfo;
        }

        // 其他文件类型不支持预览
        $previewInfo['preview_type'] = 'none';
        return $previewInfo;
    }

    /**
     * 转换为预览URL（针对Office文档）
     * @param array $file 文件信息
     * @return string 预览URL
     */
    private function convertToPreviewUrl($file)
    {
        // 这里可以集成第三方在线预览服务，如微软Office Online、Google Docs Viewer等
        // 或者使用本地服务将Office文档转换为PDF后预览
        
        // 示例：返回原始文件路径（实际项目中需要实现转换逻辑）
        return $file['filepath'];
    }

    /**
     * 获取PDF预览URL
     * @param int $id 文件ID
     * @return \think\Response
     */
    public function pdf($id)
    {
        $file = Db::name('file')->where(['id' => $id, 'user_id' => $this->uid])->find();
        if (!$file) {
            return to_assign(1, '文件不存在或无权限访问');
        }

        if (strtolower($file['fileext']) !== 'pdf') {
            return to_assign(1, '该文件不是PDF格式');
        }

        // 使用全局配置获取下载路径
        $filePath = FileUploadConfig::getDownloadPath($file);
        
        // 如果getDownloadPath返回null，表示文件不存在
        if (!$filePath) {
            return to_assign(1, '文件不存在于服务器');
        }
        
        // 确保路径使用正斜杠，避免Windows系统下的反斜杠问题
        $filePath = str_replace('\\', '/', $filePath);
        
        // 直接返回PDF文件内容
        return download($filePath, $file['name']);
    }

    /**
     * 获取图片预览URL
     * @param int $id 文件ID
     * @return \think\Response
     */
    public function image($id)
    {
        $file = Db::name('file')->where(['id' => $id, 'user_id' => $this->uid])->find();
        if (!$file) {
            return to_assign(1, '文件不存在或无权限访问');
        }

        $imageExts = ['jpg', 'jpeg', 'png', 'gif', 'bmp', 'webp'];
        if (!in_array(strtolower($file['fileext']), $imageExts)) {
            return to_assign(1, '该文件不是图片格式');
        }

        // 使用全局配置获取下载路径
        $filePath = FileUploadConfig::getDownloadPath($file);
        
        // 如果getDownloadPath返回null，表示文件不存在
        if (!$filePath) {
            return to_assign(1, '文件不存在于服务器');
        }
        
        // 确保路径使用正斜杠，避免Windows系统下的反斜杠问题
        $filePath = str_replace('\\', '/', $filePath);
        
        // 直接返回图片文件内容
        return download($filePath, $file['name']);
    }

    /**
     * 获取视频预览URL
     * @param int $id 文件ID
     * @return \think\Response
     */
    public function video($id)
    {
        $file = Db::name('file')->where(['id' => $id, 'user_id' => $this->uid])->find();
        if (!$file) {
            return to_assign(1, '文件不存在或无权限访问');
        }

        $videoExts = ['mp4', 'avi', 'mov', 'wmv', 'flv', 'mkv'];
        if (!in_array(strtolower($file['fileext']), $videoExts)) {
            return to_assign(1, '该文件不是视频格式');
        }

        // 使用全局配置获取下载路径
        $filePath = FileUploadConfig::getDownloadPath($file);
        
        // 如果getDownloadPath返回null，表示文件不存在
        if (!$filePath) {
            return to_assign(1, '文件不存在于服务器');
        }
        
        // 确保路径使用正斜杠，避免Windows系统下的反斜杠问题
        $filePath = str_replace('\\', '/', $filePath);
        
        // 直接返回视频文件内容
        return download($filePath, $file['name']);
    }

    /**
     * 获取音频预览URL
     * @param int $id 文件ID
     * @return \think\Response
     */
    public function audio($id)
    {
        $file = Db::name('file')->where(['id' => $id, 'user_id' => $this->uid])->find();
        if (!$file) {
            return to_assign(1, '文件不存在或无权限访问');
        }

        $audioExts = ['mp3', 'wav', 'wma', 'flac', 'midi'];
        if (!in_array(strtolower($file['fileext']), $audioExts)) {
            return to_assign(1, '该文件不是音频格式');
        }

        // 使用全局配置获取下载路径
        $filePath = FileUploadConfig::getDownloadPath($file);
        
        // 如果getDownloadPath返回null，表示文件不存在
        if (!$filePath) {
            return to_assign(1, '文件不存在于服务器');
        }
        
        // 确保路径使用正斜杠，避免Windows系统下的反斜杠问题
        $filePath = str_replace('\\', '/', $filePath);
        
        // 直接返回音频文件内容
        return download($filePath, $file['name']);
    }

    /**
     * 获取Office文档预览URL
     * @param int $id 文件ID
     * @return \think\Response
     */
    public function office($id)
    {
        $file = Db::name('file')->where(['id' => $id, 'user_id' => $this->uid])->find();
        if (!$file) {
            return to_assign(1, '文件不存在或无权限访问');
        }

        $officeExts = ['doc', 'docx', 'xls', 'xlsx', 'ppt', 'pptx'];
        if (!in_array(strtolower($file['fileext']), $officeExts)) {
            return to_assign(1, '该文件不是Office文档格式');
        }

        // 使用全局配置获取下载路径
        $filePath = FileUploadConfig::getDownloadPath($file);
        
        // 如果getDownloadPath返回null，表示文件不存在
        if (!$filePath) {
            return to_assign(1, '文件不存在于服务器');
        }
        
        // 确保路径使用正斜杠，避免Windows系统下的反斜杠问题
        $filePath = str_replace('\\', '/', $filePath);

        // 这里可以实现Office文档转换为PDF的逻辑
        // 示例：直接返回文件下载
        return download($filePath, $file['name']);
    }

    /**
     * 下载文件
     * @param int $id 文件ID
     * @return \think\Response|File
     */
    public function download($id)
    {
        $file = Db::name('file')->where(['id' => $id, 'user_id' => $this->uid])->find();
        if (!$file) {
            return to_assign(1, '文件不存在或无权限访问');
        }

        // 使用全局配置获取下载路径
        $filePath = FileUploadConfig::getDownloadPath($file);
        
        // 如果getDownloadPath返回null，表示文件不存在
        if (!$filePath) {
            return to_assign(1, '文件不存在于服务器');
        }
        
        // 确保路径使用正斜杠，避免Windows系统下的反斜杠问题
        $filePath = str_replace('\\', '/', $filePath);

        // 增加下载次数
        Db::name('file')->where(['id' => $id])->inc('download')->update([]);

        // 记录下载日志
        add_log('download', $id, $file, '文件下载');

        // 返回文件下载响应
        return download($filePath, $file['name']);
    }

    /**
     * 获取文件信息（用于前端预览组件）
     * @param int $id 文件ID
     * @return \think\Response
     */
    public function info($id)
    {
        $file = Db::name('file')->where(['id' => $id, 'user_id' => $this->uid])->find();
        if (!$file) {
            return to_assign(1, '文件不存在或无权限访问');
        }

        // 格式化文件大小
        $file['filesize_formatted'] = $this->formatFileSize($file['filesize']);
        
        // 获取预览类型
        $file['preview_type'] = $this->getPreviewType($file['fileext']);
        
        return to_assign(0, '获取成功', $file);
    }

    /**
     * 格式化文件大小
     * @param int $size 文件大小（字节）
     * @return string 格式化后的文件大小
     */
    private function formatFileSize($size)
    {
        $units = ['B', 'KB', 'MB', 'GB', 'TB'];
        $unitIndex = 0;
        
        while ($size >= 1024 && $unitIndex < count($units) - 1) {
            $size /= 1024;
            $unitIndex++;
        }
        
        return round($size, 2) . ' ' . $units[$unitIndex];
    }

    /**
     * 获取预览类型
     * @param string $ext 文件扩展名
     * @return string 预览类型
     */
    private function getPreviewType($ext)
    {
        $ext = strtolower($ext);
        
        // 图片
        $imageExts = ['jpg', 'jpeg', 'png', 'gif', 'bmp', 'webp'];
        if (in_array($ext, $imageExts)) {
            return 'image';
        }
        
        // PDF
        if ($ext === 'pdf') {
            return 'pdf';
        }
        
        // Office文档
        $officeExts = ['doc', 'docx', 'xls', 'xlsx', 'ppt', 'pptx'];
        if (in_array($ext, $officeExts)) {
            return 'office';
        }
        
        // 视频
        $videoExts = ['mp4', 'avi', 'mov', 'wmv', 'flv', 'mkv'];
        if (in_array($ext, $videoExts)) {
            return 'video';
        }
        
        // 音频
        $audioExts = ['mp3', 'wav', 'wma', 'flac', 'midi'];
        if (in_array($ext, $audioExts)) {
            return 'audio';
        }
        
        // 文本
        $textExts = ['txt', 'log', 'md', 'csv'];
        if (in_array($ext, $textExts)) {
            return 'text';
        }
        
        // 其他
        return 'none';
    }
}